package goldensubmarine.skoda.yeti.view.layers.content.pages.page3D.five3d

{
	import com.greensock.easing.Bounce;
	import com.greensock.easing.Quad;
	import com.greensock.easing.Quint;
	import com.greensock.TweenMax;
	import com.nuke.math.Math2;
	import com.nuke.utils.Mirror;
	import flash.display.Bitmap;
	import flash.display.Hit;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.getTimer;
	import goldensubmarine.skoda.yeti.model.PageModel;
	import goldensubmarine.skoda.yeti.vo.VO;
	import msz.framework.events.PagesEvent;
	import net.badimon.five3D.display.Scene3D;
	import net.badimon.five3D.display.Sprite3D;
	import Singularity.Geom.CatmullRom;
	import Singularity.Geom.Knot;
	import Singularity.Geom.PSpline3;
	import Singularity.Geom.Spline3;
	import Singularity.Numeric.Consts;
	/**
	 * ...
	 * @author Bartłomiej JERZY
	 */
	public class Snake extends Sprite
	{
		private var NUM							:int = 0
		private var DIFF						:Number = 0.17 
		public static const RENDER_CLEAR		:String = "renderClear"
				
		private var _scene						:Scene3D;
		private var _world						:Sprite3D;
		
		private var _data						:Object
		
		private var _center 					:Number = 0.5
		private var _left						:Number = 0
		private var _right						:Number = 1
		private var _radius						:Number = 650
		private var _spline						:PSpline3
		
		private var _zOffset					:Number = 1000
		private var _splinePos					:Array = [	
															{x:0,y:1300},
															{x:459.6,y:1109.6},
															{x:650,y:650},
															{x:468.6,y:265.35},
															{x:0,y:115},
															{x:-453.6,y:257.35},
															{x:-650,y:649.95},
															{x:-459.6,y:1109.6},
															{x:0,y:1300}

															]
														
		private var _items						:Array 				
		private var _displayList				:Array = []
		private var _knots						:Array = []
		private var _enabled					:Boolean = true
		
		private var _mid						:int
		private var _wheel						:Boolean = true
		private var _auto 						:Boolean = true
		private var _kill						:Boolean = false
		
		private var _curr						:CarouselItem
		private var _currNum					:int 
		private var _currKnot					:Knot 

		private var _splineEdit					:Sprite = new Sprite();

		private var _speed						:Number = 0;
		private var _render						:LoopRender
			
		
		
		public function Snake($data:Object=null) 
		{
			if ($data) {
				_data = []
			
				for (var j:String in $data.item) {
					_data[j] = $data.item[j]
				}
			}
			
			addEventListener(Event.ADDED_TO_STAGE,init)
			
			DIFF = 1/_data.length
			
			
			NUM = _data.length
			
			
		}
	
		private function init(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init)
			
			initSpline()
			initWorld()
			initSnake()
			initRender()
			
			
			PageModel.addEventListener(PageModel.PLAYER_HIDDEN,playerHidden)
			//initSplineEditor()
			
			/*trace("#### KNOT COORD")
			for (var i:int = 0; i < 9; i++) {
				trace("{x:",Math.sin((i*45)*Math.PI/180)*_radius,",y:",Math.cos((i*45)*Math.PI/180)*_radius+_radius,"}",i*45)
			}*/
		}
		
		private function initRender():void{
			_render = new LoopRender()
			_render.addEventListener(PagesEvent.ON_CLEAR,destroy)
			_world.addChild(_render)
			_world.y = 150
			_render.x = -_render.width/2
			_render.z = _radius / 2+400
			
			TweenMax.from(_render,0.4,{alpha:0,onComplete:initialized})
			
		}
		
		private function initialized():void
		{
			dispatchEvent(new Event(Event.COMPLETE))
		}
			
		private function oef(e:Event):void 
		{
			if (_enabled) {
				position()
				render()
			}
			
		}
				
		private function initEvents():void
		{
			if(_items.length >0) this.addEventListener(Event.ENTER_FRAME,oef)
		}
	
		private function initSnake():void
		{
			var _delay:int = 5
			var _num:int = 0
			
			
			if (_items) {
				for (var j:String in _items ) {
					_items[j].removeEventListener(PagesEvent.ON_CLEAR, onItemCleared)
					_items[j].removeEventListener(Event.SELECT, onItemClicked)
					_items[j].hideAndClear()
				}
			}
			
			_items = []
			
			for (var i:String in _data ) {
				
				_items[_num] = new CarouselItem(_data[i])
				_items[_num].y = 150 + Math2.randRange(0, 5) * ( -30)
				_items[_num].t = 0.5+DIFF*_num-(NUM-1)*DIFF/2
				_items[_num].scaleX = 0.5
				_items[_num].scaleY = 0.5
				_items[_num].scaleZ = 0.5
				_items[_num].addEventListener(PagesEvent.ON_CLEAR, onItemCleared)
				_items[_num].addEventListener(Event.SELECT, onItemClicked)
				
				_displayList[_num] = _items[_num]
					
				if (_items[_num].t >= 0 && _items[_num].t <= 1) {
					_world.addChild(_items[_num])
					
					setPosition(_items[_num])
					setAngle(_items[_num])
					
					_items[_num].visible = false
					
					TweenMax.to(_items[_num], 20, { y:_items[_num].y, autoAlpha:1, useFrames:true, startAt: { y:_items[_num].y -800, autoAlpha:0 }, delay:_delay,ease:Quint.easeOut } )
					
					_delay += 3
				}
				_num++
			}
			
			TweenMax.delayedCall(_delay+10,initEvents,null,true)
			_curr = _items[0]
		}
		
		private function onItemClicked(e:Event):void 
		{
			enabled = false
			_curr = e.currentTarget as CarouselItem
			_curr.hideTitle(true)
			TweenMax.to(e.currentTarget,0.3,{scaleX:1,scaleY:1,scaleZ:1,z:0,x:-55,y:0,rotationX:0,rotationY:0,rotationZ:0,ease:Quint.easeOut,onComplete:showPlayer,onCompleteParams:[e.currentTarget.data.video[0]]})
		}
		
		private function showPlayer($v:String):void
		{
			PageModel.video = $v
		}
		
			
		private function playerHidden(e:Event):void 
		{
			
			var _x:Number =  _spline.getX(_curr.t)
			var _z:Number = _spline.getY(_curr.t)
			var _deltaX:Number  = _spline.getX(_curr.t - 0.0001) - _spline.getX(_curr.t + 0.0001)
			var _deltaZ:Number  = _spline.getY(_curr.t - 0.0001) - _spline.getY(_curr.t + 0.0001)
		
			var _angle:Number = 0
			_angle = Math.atan2(-_deltaZ, _deltaX)
			_curr.hideTitle(false)				
			TweenMax.to(_curr,0.3,{scaleX:.5,scaleY:.5,scaleZ:.5,z:_z,x:_x,y:150 + Math2.randRange(0, 5) * ( -30),rotationX:0,rotationY:_angle * Consts.RAD_TO_DEG,rotationZ:0,ease:Quint.easeInOut,onComplete:function():void{enabled = true}})
		}
		
		
		private function initWorld():void
		{
			
			_scene = new Scene3D();
			_scene.viewDistance = 700
			_world = new Sprite3D()
			_world.childrenSorted  = true
			//_world.flatShaded = true
			
			_scene.addChild(_world);
			addChild(_scene);
					
		}
		
		private function initSpline():void
		{
			_spline = new PSpline3()
			for (var i:String in _splinePos) {
				_spline.addControlPoint(_splinePos[i].x,_splinePos[i].y)
			}
		}
		
		private function position():void {
			
			_speed = (_scene.mouseX/stage.stageWidth) / 50
			_render.speed = _speed * 600//180
			
			for (var i:int = 0; i < _items.length; i++) {
				_items[i].t += _speed
				_items[i].rotationZ = -_speed*500
				_items[i].rotationX = _speed*500
				if (_speed < 0) {
					if (_items[i].t < _left) {
						_items[i].t = _right + _items[i].t
					}
				}else {
					if (_items[i].t > _right) {
						_items[i].t =   _items[i].t-_right 
					}
				}
				
			}
			
			//alignItems()
			
		}
		
		private function sortFunc($a:Object,$b:Object):int {
			if ($a.t > $b.t) {
				return 1 
			}else if ($a.t < $b.t) {
				return -1 
			}else {
				return 0
			}
			 
		}
		
		private function alignItems():void {
			if (_currNum) {
				for (var i:int = _items.length-2; i >= 0; i--) {
					_items[i].t = _items[i + 1].t - DIFF
				}
			}else {
				for (var j:int = 1; j < _items.length; j++) {
					_items[j].t = _items[j - 1].t + DIFF
					
				}
			}
		}
		
		private function render():void {
		
			for (var i:int = 0; i < _items.length; i++) {
				setPosition(_items[i])
				setAngle(_items[i])
			}
			
		}
		
		private function setAngle($item:CarouselItem):void {
			
			var _deltaX:Number  = _spline.getX($item.t - 0.0001) - _spline.getX($item.t + 0.0001)
			var _deltaZ:Number  = _spline.getY($item.t - 0.0001) - _spline.getY($item.t + 0.0001)
		
			var _angle:Number = 0
			_angle = Math.atan2(-_deltaZ, _deltaX)
			
			$item.rotationY  = _angle * Consts.RAD_TO_DEG
		}
		
		private function setPosition($item:CarouselItem):void {
			$item.x = _spline.getX($item.t)
			$item.z = _spline.getY($item.t)
		}
			
		public function hideAndClear():void {
			_enabled = false
			_kill = true
			_render.enabled = false
			_render.tweenFrame(1)
			for (var i:String in _items) {
				_items[i].hideAndClear()
			}
		}
				
		private function onItemCleared(e:PagesEvent):void 
		{
			NUM--
			if (!NUM && _kill) {
				dispatchEvent(new Event(Snake.RENDER_CLEAR))
				_render.hideAndClear()
			}
		}
				
		public function destroy(e:Event = null):void {
			removeEventListener(Event.ENTER_FRAME, oef)
			PageModel.removeEventListener(PageModel.PLAYER_HIDDEN,playerHidden)
			_world.removeChild(_render)
			_scene.removeChild(_world);
			removeChild(_scene);
			
			for (var i:String in _items) {
				if(_world.contains(_items[i])) _world.removeChild(_items[i])
			}
			
			
			_render = null
			_world = null		
			_scene = null		
			_items = null
			_displayList = null
			_spline = null
			
			dispatchEvent(new PagesEvent(PagesEvent.ON_CLEAR))
		}
		
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		private function initSplineEditor():void
		{
			_splineEdit = new Sprite()
			var _sh:Hit= new Hit()
			_spline.container = _sh
			
			_splineEdit.addChild(_sh)
			
			for (var i:String in _splinePos) {
				_knots[i] = new Knot(10,0xff0000)
				_knots[i].x = _splinePos[i].x
				_knots[i].y = _splinePos[i].y
				_knots[i].addEventListener(MouseEvent.MOUSE_DOWN, knotMouseDown, false, 0, true)
				_knots[i].id = i
				_splineEdit.addChild(_knots[i])
			}
			
			_spline.color = 0xff0000
			_spline.draw()
					
			
			addChild(_splineEdit)
		}
		
		
		private function knotMouseDown(e:MouseEvent):void 
		{
			stage.addEventListener(MouseEvent.MOUSE_MOVE,knotMouseMove,false,0,true)
			stage.addEventListener(MouseEvent.MOUSE_UP, knotMouseUp, false, 0, true)
			
			_currKnot = e.target as Knot
			_currKnot.startDrag()
		}
		private function knotMouseMove(e:MouseEvent):void 
		{
			_spline.moveControlPoint(_currKnot.id,_currKnot.x,_currKnot.y)
			_spline.draw()
		}
		private function knotMouseUp(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE,knotMouseMove)
			stage.removeEventListener(MouseEvent.MOUSE_UP, knotMouseUp)
			_currKnot.stopDrag()
			
			trace("#### KNOTS COORDS ####")
			
			for (var i:String in _knots) {
				trace("{x:"+_knots[i].x+",y:"+_knots[i].y+"}")
			}
		}
		
		public function get enabled():Boolean { return _enabled; }
		
		public function set enabled(value:Boolean):void 
		{
			_enabled = value;
			_render.enabled = _enabled
		}
		
		public function get data():Object { return _data; }
		
		public function set data(value:Object):void 
		{
			_data =[]
			
			for (var i:String in value.item) {
				_data[i] = value.item[i]
			}
			
			DIFF = 1/_data.length
			NUM = _data.length
			
			initSnake()
			
		}
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////
	}

}